// Copyright (c) 2024-present AI-Labs

// @ ts-nocheck
import CodeBlock from '@tiptap/extension-code-block-lowlight';
import { common, createLowlight } from 'lowlight';
import { Node } from 'prosemirror-model';

import { t } from "i18next"

const lowlight = createLowlight(common);

export default CodeBlock.configure({
    lowlight,
}).extend({
    addAttributes() {
        return {
            ...this.parent?.(),
            language: {
                default: 'plaintext',
            },
            theme: {
                default: 'light',
            },
            wordWrap: {
                default: true,
            },
        }
    },
    addNodeView() {
        return (props) => {
            const wrapper = document.createElement('div');
            wrapper.classList.add('uai-node-view');
            wrapper.classList.add('uai-node-code-block');

            const container = document.createElement('div');
            container.style.width = '100%';
            wrapper.appendChild(container);

            const toolbar = document.createElement('div');
            toolbar.classList.add('uai-node-code-block-toolbar');
            container.appendChild(toolbar);

            const toolbarLeft = document.createElement('div');
            toolbarLeft.classList.add('uai-node-code-block-toolbar-left');

            // 添加语言选择下拉框
            const languageSelect = document.createElement('select');
            languageSelect.classList.add('uai-node-code-block-language-select');
            languageSelect.innerHTML = lowlight.listLanguages().map((item) => {
                return `<option value="${item}">${item}</option>`;
            }).join('');
            languageSelect.value = props.node.attrs.language;
            toolbarLeft.appendChild(languageSelect);

            // 添加主题选择下拉框
            const themeSelect = document.createElement('select');
            themeSelect.classList.add('uai-node-code-block-theme-select');
            themeSelect.innerHTML = `
                <option value="light">${t("codeBlock.theme.light")}</option>
                <option value="dark">${t("codeBlock.theme.dark")}</option>
            `;
            themeSelect.value = props.node.attrs.theme || 'light';
            toolbarLeft.appendChild(themeSelect);

            toolbar.appendChild(toolbarLeft);

            const toolbarRight = document.createElement('div');
            toolbarRight.classList.add('uai-node-code-block-toolbar-right');
            const copyButton = document.createElement('button');
            copyButton.className = 'uai-node-code-block-toolbar-button';
            copyButton.textContent = t("codeBlock.tools.copy");
            toolbarRight.appendChild(copyButton);
            toolbar.appendChild(toolbarRight);

            const contentContainer = document.createElement('div');
            contentContainer.classList.add('uai-node-code-block-content-container');
            container.appendChild(contentContainer);

            const lineNumbers = document.createElement('div');
            lineNumbers.classList.add('uai-node-code-block-line-numbers');
            lineNumbers.setAttribute('aria-hidden', 'true');
            contentContainer.appendChild(lineNumbers);

            const codeBlock = document.createElement('pre');
            codeBlock.classList.add('hljs');

            const code = document.createElement('code');
            code.classList.add('hljs');
            code.classList.add(`language-${props.node.attrs.language}`);
            codeBlock.appendChild(code);
            contentContainer.appendChild(codeBlock);

            const updateLineNumbers = (node: Node) => {
                const lineCount = node.textContent.split('\n').length;
                if (lineNumbers.childElementCount !== lineCount) {
                    lineNumbers.innerHTML = Array.from({ length: lineCount }, (_, i) => `<div>${i + 1}</div>`).join('');
                }
            };

            const updateTheme = (node: Node) => {
                // 更新主题选择
                themeSelect.value = node.attrs.theme || 'light';

                // 根据主题设置更新样式
                if (node.attrs.theme === 'dark') {
                    toolbar.classList.add('uai-theme-dark');
                    languageSelect.classList.add('uai-theme-dark');
                    themeSelect.classList.add('uai-theme-dark');
                    copyButton.classList.add('uai-theme-dark');
                    contentContainer.classList.add('uai-theme-dark');
                    lineNumbers.classList.add('uai-theme-dark');
                    codeBlock.classList.add('uai-theme-dark');
                    code.classList.add('uai-theme-dark');
                } else {
                    toolbar.classList.remove('uai-theme-dark');
                    languageSelect.classList.remove('uai-theme-dark');
                    themeSelect.classList.remove('uai-theme-dark');
                    copyButton.classList.remove('uai-theme-dark');
                    contentContainer.classList.remove('uai-theme-dark');
                    lineNumbers.classList.remove('uai-theme-dark');
                    codeBlock.classList.remove('uai-theme-dark');
                    code.classList.remove('uai-theme-dark');
                }
            };

            languageSelect.addEventListener('change', () => {
                props.editor.chain().focus().setCodeBlock({
                    language: languageSelect.value
                }).run();
            });
            themeSelect.addEventListener('change', () => {
                props.editor.chain().focus().updateAttributes('codeBlock', {
                    theme: themeSelect.value
                }).run();
            });
            copyButton.addEventListener('click', () => {
                const codeText = code.innerText;
                navigator.clipboard.writeText(codeText).then(() => {
                    // 可以添加一些用户反馈，比如临时改变按钮文字为 "Copied!"
                    const originalText = copyButton.textContent;
                    copyButton.textContent = 'Copied!';
                    setTimeout(() => {
                        copyButton.textContent = originalText;
                    }, 2000);
                }).catch(err => {
                    console.error('Failed to copy code: ', err);
                });
            });

            updateTheme(props.node);
            updateLineNumbers(props.node);

            return {
                dom: wrapper,
                contentDOM: code,
                update: (node) => {
                    if (node.type.name !== 'codeBlock') {
                        return false;
                    }

                    code.className = `hljs language-${node.attrs.language}`;
                    languageSelect.value = node.attrs.language;

                    updateTheme(node);
                    updateLineNumbers(node);

                    return true;
                },
            }
        }
    },
});